package com.dding.cms.base.web;

import static com.dding.cms.base.web.util.PersistenceUtil.deleteBo;
import static com.dding.cms.base.web.util.PersistenceUtil.deleteCascadeBo;
import static com.dding.cms.base.web.util.PersistenceUtil.updateBo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringTokenizer;

import org.dding.core.annotation.Service;
import org.dding.core.log.ILogger;
import org.dding.core.log.LoggerFactory;
import org.dding.core.util.StringUtils;
import org.dding.mvc.ActionSupport;
import org.dding.mvc.InvocationContext;
import org.dding.mvc.annotation.ActionMethod;
import org.dding.mvc.annotation.ActionMethod.ForwardMethod;
import org.javalite.activejdbc.LazyList;
import org.javalite.activejdbc.Model;

import com.dding.cms.base.entity.BaseModel;
import com.dding.cms.base.entity.BaseModelItem;
import com.dding.cms.base.web.bo.BaseModelBO;
import com.dding.cms.base.web.bo.BaseModelItemBO;
import com.dding.cms.base.web.util.Configuration;
import com.dding.cms.base.web.util.Utils;

@Service(name = "modelAction")
public class ModelAction extends ActionSupport<Object> {

	ILogger logger = LoggerFactory.getLogger(getClass());
	
	@SuppressWarnings("rawtypes")
	private static Set itemColums;

	@SuppressWarnings("rawtypes")
	private static Set modelColums;

	@ActionMethod(
			name = "list", successView = "list.jsp", errorView = "error.html",
			httpMethod = ActionMethod.HttpMethod.ALL)
	public void list(InvocationContext invocationContext) {
		@SuppressWarnings("unchecked")
		LazyList<Model> modelList = BaseModel.findAll();
		List<BaseModelBO> models = new ArrayList<BaseModelBO>();
		for (Model model : modelList.toArray(new Model[0])) {
			BaseModelBO BaseModelBO = (BaseModelBO) Utils.buildBO(model,
					BaseModelBO.class);
			models.add(BaseModelBO);
		}
		invocationContext.getPageContext().setAttribute("models", models);
	}

	@ActionMethod(
			name = "add", successView = "list.do", errorView = "error.html",
			httpMethod = ActionMethod.HttpMethod.POST)
	public void add(InvocationContext invocationContext) {
		Map<String, String[]> modelMap = invocationContext.getParameterMap();
		BaseModel model = new BaseModel();
		initColumns();
		for (Entry<String, String[]> entry : modelMap.entrySet()) {
			if (modelColums.contains(entry.getKey())) {
				model.set(entry.getKey(), entry.getValue()[0]);
			}
		}
		model.save();
	}

	@ActionMethod(
			name = "edit", successView = "edit.jsp", errorView = "error.html",
			httpMethod = ActionMethod.HttpMethod.GET)
	public void edit(InvocationContext invocationContext) {
		String id = invocationContext.getParameterValue("id");
		if (!StringUtils.isEmpty(id)) {
			Model model = BaseModel.findById(id);
			BaseModelBO channelModelBO = (BaseModelBO) Utils.buildBO(model,
					BaseModelBO.class);
			invocationContext.getPageContext().setAttribute("bo",
					channelModelBO);
		}
	}

	@SuppressWarnings("unchecked")
	@ActionMethod(
			name = "update", successView = "list.do", errorView = "error.html",
			httpMethod = ActionMethod.HttpMethod.POST)
	public void update(InvocationContext invocationContext) {
		initColumns();
		updateBo(invocationContext, modelColums, BaseModel.class, "model_id");
	}

	@ActionMethod(
			name = "delete", errorView = "error.html",
			forwardMethod = ForwardMethod.FLUSH)
	public void delete(InvocationContext invocationContext) {
		deleteCascadeBo(invocationContext, new BaseModel(), "model_id");
	}

	@ActionMethod(
			name = "save", errorView = "error.html",
			forwardMethod = ForwardMethod.FLUSH)
	public void save(InvocationContext invocationContext) {
		String[] trs = invocationContext.getParameterValues("ids");
		Map<String, String> result = new HashMap<String, String>();
		if (trs == null || trs.length == 0) {
			result.put(STATUS, FAILURE);
			result.put(MESSAGE, "没有记录被选中");
		} else {
			Object[][] params = new Object[trs.length][4];
			String query = "is_disabled = ?,priority = ?,is_def = ?";
			String conditions = "model_id = ?";
			for (int i = 0; i < trs.length; i++) {
				StringTokenizer token = new StringTokenizer(trs[i], "$");
				while (token.hasMoreTokens()) {
					String para = token.nextToken();
					if (para != null & !"".equals(para)) {
						String[] temp = para.split("->");
						if ("model_id".equals(temp[0])) {
							params[i][3] = temp[1];
						}
						if ("is_disabled".equals(temp[0])) {
							if (Boolean.parseBoolean(temp[1]))
								params[i][0] = "0";
							else
								params[i][0] = "1";
						}
						if ("priority".equals(temp[0])) {
							params[i][1] = temp[1];
						}
						if ("is_def".equals(temp[0])) {
							if (Boolean.parseBoolean(temp[1]))
								params[i][2] = "1";
							else
								params[i][2] = "0";
						}
					}
				}
			}
			BaseModel.update(query, conditions, params);
			result.put(STATUS, SUCCESS);
			result.put(MESSAGE, "保存成功.");
		}
		ajaxJsonMessage(result, invocationContext);
	}

	@ActionMethod(
			name = "save_singles", errorView = "error.html",
			httpMethod = ActionMethod.HttpMethod.ALL,
			forwardMethod = ForwardMethod.FLUSH)
	@SuppressWarnings("unchecked")
	public void saveSingles(InvocationContext invocationContext) {
		String[] trs = invocationContext.getParameterValues("singles");
		Map<String, String> result = new HashMap<String, String>();
		if (trs == null || trs.length == 0) {
			result.put(STATUS, FAILURE);
			result.put(MESSAGE, "没有记录被选中");
		} else {
			String query = "is_single = 1";
			String condition = "modelitem_id = ?";
			Object[][] params = new Object[trs.length][1];
			for (int i = 0; i < trs.length; i++) {
				params[i][0] = trs[i];
			}
			BaseModelItem.update(query, condition, params);
			result.put(STATUS, SUCCESS);
			result.put(MESSAGE, "保存成功.");
		}
		ajaxJsonMessage(result, invocationContext);
	}

	@ActionMethod(
			name = "modelChannel", errorView = "error.html",
			successView = "channel.jsp",
			httpMethod = ActionMethod.HttpMethod.ALL)
	@SuppressWarnings("unchecked")
	public void modelChannel(InvocationContext invocationContext) {
		String model_type = invocationContext.getParameterValue("model_type");
		String id = invocationContext.getParameterValue("model_id");
		if (StringUtils.isEmpty(model_type) || StringUtils.isEmpty(id)) {
			return;
		}
		LazyList<Model> modelItems = null;
		if ("1".equals(model_type)) {
			modelItems = BaseModelItem.find("model_id=? and model_type=?",
					new Object[] { id, 1 });
		} else if ("2".equals(model_type)) {
			modelItems = BaseModelItem.find("model_id=? and model_type=?",
					new Object[] { id, 2 });
		}

		List<BaseModelItemBO> itemshow = new ArrayList<BaseModelItemBO>();
		List<BaseModelItemBO> itemhide = new ArrayList<BaseModelItemBO>();
		for (Model model : modelItems.toArray(new Model[0])) {
			BaseModelItemBO item = (BaseModelItemBO) Utils.buildBO(model,
					BaseModelItemBO.class);
			item.setDataTypeMapping(Configuration.getDataTypeMapping().get(item
					.getData_type()));
			if (item.getIs_display()) {
				itemshow.add(item);
			} else {
				itemhide.add(item);
			}
		}
		Collections.sort(itemshow, new PriorityComparator());
		Collections.sort(itemhide, new PriorityComparator());
		invocationContext.getPageContext().setAttribute("itemshow", itemshow);
		invocationContext.getPageContext().setAttribute("itemhide", itemhide);
		invocationContext.getPageContext().setAttribute("model_id", id);
		invocationContext.getPageContext().setAttribute("model_type",
				model_type);
	}

	@ActionMethod(
			name = "beforeAddModelChannel", errorView = "error.html",
			successView = "addChannelModel.jsp",
			forwardMethod = ForwardMethod.FORWARD,
			httpMethod = ActionMethod.HttpMethod.GET)
	public void beforeAddModelChannel(InvocationContext invocationContext) {
		invocationContext.getPageContext().setAttribute("mapping",
				Configuration.getDataTypeMapping());
	}

	@ActionMethod(
			name = "addModelChannel", errorView = "error.html",
			successView = "modelChannel.do",
			httpMethod = ActionMethod.HttpMethod.POST)
	public void addModelChannel(InvocationContext invocationContext) {
		Map<String, String[]> itemMap = invocationContext.getParameterMap();
		BaseModelItem item = new BaseModelItem();
		initColumns();
		for (Entry<String, String[]> entry : itemMap.entrySet()) {
			if (itemColums.contains(entry.getKey())) {
				item.set(entry.getKey(), entry.getValue()[0]);
			}
		}
		item.save();
	}

	@ActionMethod(
			name = "deleteModelChannel", errorView = "error.html",
			forwardMethod = ForwardMethod.FLUSH)
	public void deleteModelChannel(InvocationContext invocationContext) {
		deleteBo(invocationContext, BaseModelItem.class, "modelitem_id=?");
	}

	@SuppressWarnings("unchecked")
	@ActionMethod(
			name = "updateModelChannel", successView = "modelChannel.do",
			errorView = "error.html",
			httpMethod = ActionMethod.HttpMethod.POST,
			forwardMethod = ForwardMethod.FORWARD)
	public void updateModelChannel(InvocationContext invocationContext) {
		initColumns();
		updateBo(invocationContext, itemColums, BaseModelItem.class,
				"modelitem_id");
	}

	@ActionMethod(
			name = "editModelChannel", successView = "editChannelModel.jsp",
			errorView = "error.html", httpMethod = ActionMethod.HttpMethod.GET)
	public void editModelChannel(InvocationContext invocationContext) {
		String id = invocationContext.getParameterValue("id");
		if (!StringUtils.isEmpty(id)) {
			Model model = BaseModelItem.findById(id);
			BaseModelItemBO item = (BaseModelItemBO) Utils.buildBO(model,
					BaseModelItemBO.class);
			invocationContext.getPageContext().setAttribute("bo", item);
			invocationContext.getPageContext().setAttribute("mapping",
					Configuration.getDataTypeMapping());
		}
	}

	private void initColumns() {
		if (itemColums == null)
			itemColums = BaseModelItem.getMetaModel().getColumnMetadata()
					.keySet();
		if (modelColums == null)
			modelColums = BaseModel.getMetaModel().getColumnMetadata().keySet();
	}

	class PriorityComparator implements Comparator<BaseModelItemBO> {

		@Override
		public int compare(BaseModelItemBO o1, BaseModelItemBO o2) {
			return o1.getPriority() - o2.getPriority();
		}
	}
}